package com.gxm.练习.手写.arrylist;

import com.gxm.base.thowable.RRException;

import java.util.Arrays;

/**
 *
 * @param <E>
 * 核心
 *      扩容
 *          添加时
 *              Arrays.copyOf()
 *              System.arraycopy()
 *          删除时
 *              System.arraycopy()
 */
public class JdkArrayList<E> implements JdkList<E> {

    //定义一个存储的容器数组
    private Object[] elementData;
    //定义默认容器的容量
    private final static int INIT_NUM = 10;
    //当前容器存储的元素个数
    private int size;

    public JdkArrayList(){
        this(INIT_NUM);
    };

    public JdkArrayList(int initNum){
        if (initNum < 0) {
            throw new RRException("集合容量不可小于0");
        }
        elementData = new Object[initNum];
    }

    @Override
    public void add(E e) {
        //什么时候扩容? 扩容的条件是什么? 要装满了就扩容
        //如果已存入的数量和当前 数组容器的容量相等时
        ensureExplicitCapacity();
        elementData[size++] = e;
    }


    @Override
    public void add(int index, E e) {
        indexOutCheck(index);
        ensureExplicitCapacity();
        //从指定位置 向后移一位 后 把 元素 添加到 指定位置
        System.arraycopy(elementData, index, elementData, index + 1, size - index);
        elementData[index] = e;
        size++;
    }

    @Override
    public E remove(int index) {
        indexOutCheck(index);
        int numMoved = elementData.length - index - 1;
        if (numMoved > 0){
            //从指定位置 向前移一位 后 把 元素 添加到 指定位置
            System.arraycopy(elementData, index + 1, elementData, index, size - index);
        }
        elementData[--size] = null;
        return null;
    }

    @Override
    public boolean remove(E e) {
        for (int i = 0; i < elementData.length; i++) {
            if(elementData[i].equals(e)){
                remove(i);
                return true;
            }
        }
        return false;
    }

    @Override
    public E get(int index) {
        return (E) elementData[index];
    }

    private void ensureExplicitCapacity() {
        if(size == elementData.length){
            int minCapacity = size + 1;
            elementData = Arrays.copyOf(elementData,elementData.length >> 1);
            // 获取原来数组的长度 2
            int oldCapacity = elementData.length;
            // oldCapacity >> 1 理解成 oldCapacity/2 新数组的长度是原来长度1.5倍
            int newCapacity = oldCapacity + (oldCapacity >> 1); // 3
            if (newCapacity < minCapacity) {
                // 最小容量比新容量要小的,则采用初始容量minCapacity
                newCapacity = minCapacity;
            }
            Arrays.copyOf(elementData,newCapacity);
        }
    }

    private void indexOutCheck(int index){
        if(index >= size){
            throw new RRException("角标越界了");
        }
    }
}
